import BaseEntity from "@/type/BaseEntity";
import {App, Button, Card, Form, Space, Spin} from "antd";
import {Link} from "react-router-dom";
import React, {useEffect, useRef, useState} from "react";
import LogFactory from "@/log/LogFactory.ts";
import {CloudUploadOutlined, UndoOutlined} from "@ant-design/icons";
import RequestHandler from "@/http/RequestHandler.ts";
import {compareObject} from "@/util/compare.ts";

// 互斥更新和添加相关属性
type UpdateProps = {
    /**
     * 表单执行类型: 更新表单
     */
    update: true;
    /**
     * 表单更新url地址
     */
    updateUrl: string;
    /**
     * 表单执行类型: 添加数据表单
     */
    add?: false;
    /**
     * 表单添加数据url地址
     */
    addUrl?: never;
}
type AddProps = {
    update?: false;
    updateUrl?: never;
    add: true;
    addUrl: string;
}
type BaseProps<T extends BaseEntity> = {
    /**
     * 表单名称
     */
    name?: string,
    /** 表单标题 */
    title?: string,
    /**
     * 反回文本
     */
    backText?: string,
    /**
     * 初始化数据
     */
    initialValues?: Partial<T>,
    /**
     * 初始化数据的url
     */
    initialDataUrl: string,
    /**
     * 表单提交之前的自定义数据转换函数
     * @param formData
     */
    formDataConvert?: (formData: T) => T,
    /**
     * 表单项目
     */
    children: React.ReactNode
}
type ProFormPros<T extends BaseEntity> = BaseProps<T> & (UpdateProps | AddProps);

const log = LogFactory.getLogger("ProForm");
/**
 * 高级表单增强组件
 * @param props 表单属性
 */
const ProForm = <T extends BaseEntity>(props: ProFormPros<T>) => {
    const {formDataConvert} = props;
    const [loading, setLoading] = useState<boolean>(true);
    const [form] = Form.useForm<T>();
    const {message} = App.useApp();
    const dataRef = useRef<T>();

    useEffect(() => {
        RequestHandler.get<T>(props.initialDataUrl)
            .then(res => {
                dataRef.current = res.data;
                form.setFieldsValue(res.data as object);
                setLoading(false);
            });
    },[])

    const onFinish = async (values: T) => {
        setLoading(true);
        if (formDataConvert) {
            values = formDataConvert(values);
        }
        log.debug("finish", values);
        if (props.update){
            const compare = compareObject(dataRef.current!, values);
            if (compare == null){
                return;
            }
            compare.id = dataRef.current!.id;
            const serverRes = await RequestHandler.post<number>(props.updateUrl, compare);
            if (serverRes.success){
                message.success("表单数据提交成功!");
            }

            log.debug("更新数据比较结果: ", compare);
            // await message.success("表单数据提交成功!7pk1872b");
        }
        setLoading(false);
    }
    return (
        <Card title={props.title} extra={<Link to={".."}>{props.backText}</Link>}>
            <Spin spinning={loading}>
                <Form<T>
                    form={form}
                    style={{}}
                    name={props.name}
                    labelAlign={"right"}
                    labelCol={{span: 5}}
                    wrapperCol={{span: 14}}
                    initialValues={props.initialValues}
                    onFinish={onFinish}
                >
                    {props.children}
                    <Form.Item wrapperCol={{offset: 8, span: 16}}>
                        <Space size={30}>
                            <Button icon={<CloudUploadOutlined />} loading={loading} type="primary" htmlType="submit">
                                提交表单
                            </Button>
                            <Button icon={<UndoOutlined />} loading={loading} htmlType="reset">
                                重置表单
                            </Button>
                        </Space>
                    </Form.Item>
                </Form>
            </Spin>
        </Card>
    );
};

export default ProForm;